#ifndef OPENHITLS_KAE_DH_H
#define OPENHITLS_KAE_DH_H

#include "bsl_params.h"
#include "crypt_algid.h"
#include "crypt_bn.h"
#include "wd.h"
#include "wd_dh.h"

#define DH_MAX_PBITS 8192
#define DH_MIN_PBITS 768
#define DH_MIN_QBITS 160
#define DH_BITS_SIZE 5

#define KAE_DH_SET_G_ERROR    0x010C1001
#define KAE_DH_GEN_ERROR      0x010C1002
#define KAE_DH_GEN_SHARED_ERROR      0x010C1003

static const uint32_t DH_BITS[DH_BITS_SIZE] = {768, 1024, 2048, 3072, 4096};

typedef int32_t (*GetLenFunc)(const void *ctx);

typedef struct DH_Para {
    BN_BigNum *p;
    BN_BigNum *q;
    BN_BigNum *g;
    CRYPT_PKEY_ParaId id;
} DH_Para;

typedef struct KAE_DH_Ctx
{
    struct wd_queue                     queue;
    struct wd_queue_mempool*            pool;
    struct wcrypto_dh_ctx_setup         setup;
    struct wcrypto_dh_op_data           opData;
    void*                               dhCtx;
    DH_Para*                            para;
    BN_BigNum*                          prvKey;
    BN_BigNum*                          pubKey;
} KAE_DH_Ctx;

KAE_DH_Ctx* KAE_DH_NewCtx();

int32_t KAE_DH_SetPara(KAE_DH_Ctx* ctx, const BSL_Param *para);

int32_t KAE_DH_GetPara(const KAE_DH_Ctx* ctx, BSL_Param *param);

int32_t KAE_DH_GetPrvKey(const KAE_DH_Ctx *ctx, BSL_Param *para);

int32_t KAE_DH_GetPubKey(const KAE_DH_Ctx *ctx, BSL_Param *para);

int32_t KAE_DH_SetPrvKey(KAE_DH_Ctx *ctx, const BSL_Param *para);

int32_t KAE_DH_SetPubKey(KAE_DH_Ctx *ctx, const BSL_Param *para);

int32_t KAE_DH_Gen(KAE_DH_Ctx *ctx);

int32_t KAE_DH_Ctrl(KAE_DH_Ctx* ctx, int32_t opt, void *val, uint32_t len);

KAE_DH_Ctx* KAE_DH_DupCtx(KAE_DH_Ctx* ctx);

int32_t KAE_DH_Cmp(const KAE_DH_Ctx *a, const KAE_DH_Ctx *b);

int32_t KAE_DH_ComputeShareKey(const KAE_DH_Ctx *ctx, const KAE_DH_Ctx *pubKey, uint8_t *out, uint32_t *outLen);

void KAE_DH_Free(KAE_DH_Ctx* ctx);

#endif